var _ = require('lodash'),
    Q = require('q'),
    mongoose = require('mongoose'),
    entityCollection = require('../../../Base/server/controllers/EntityCollection'),
    userController = require('../../../User/server/controllers/users.server.controller'),
    BarcodeEnum = require('../../../Barcode/server/controllers/Enum.server.controller'),
    Transaction = require('../../../Base/server/controllers/Transaction'),
    PublicEnum = require('../../../Base/server/controllers/Enum'),
    QCEnum = require('../../../QC/server/controllers/Enum.server.controller'),
    operationController = require('../../../CBO/server/controllers/Operation.server.controller'),
    processExceptionController = require('../../../Barcode/server/controllers/ProcessException.server.controller');

//对包装货号新增条码主档
exports.insertPackageBarcode = function (packageBarcode, completeFun) {
    var entity = entityCollection.getEntity("BarcodeMaster");
    entity.findOne({Barcode: packageBarcode}, null,
        function (err, record) {
            if (err) {
                var newErr = new Error();
                newErr.leval = 9;
                newErr.title = '查询条码主档错误';
                newErr.message = '查询失败，请检查查询参数！';
                completeFun(newErr);
            } else {
                if(record){
                    completeFun(null, record);
                }
                else{
                    var insertData = {
                        Barcode: packageBarcode,
                        BarcodeType: 6
                    }
                    entity.insert(insertData, function (err, Record) {
                        completeFun(err, Record);
                    });
                }
                
            }
        });
    
};

//创建多条入库记录
exports.addPackageRecords = function (barcodeMasters, userId, completeFun) {

    // console.log(barcodeMasters);

    barcodeMasters.forEach(function (barcodeMaster) {


        barcodeMaster.RowStatus = PublicEnum.RowStatus.Insert;
        barcodeMaster.CreatedBy = userId;
    });

    addPackage(barcodeMasters).then(function (result) {
        completeFun(null, result);
    }, function (err) {
        var newErr = new Error();
        newErr.leval = 9;
        newErr.title = '创建入库记录失败';
        newErr.message = '';
        completeFun(newErr);

    });

};

function addPackage(barcodeMasters) {
    var deferred = Q.defer();
    Transaction.BatchSaveByTran([
            {EntityName: 'RcvRecord', Records: barcodeMasters}
        ],
        function (err, result) {
            if (err) {
                deferred.reject(err);
                return;
            }
            deferred.resolve(result);
        }
    );
    return deferred.promise;
}

//创建多条条码装配关系
exports.addPackageAssemblyRelations = function (packageBarcodeID, barcodeMasters, completeFun) {

    var dateNow = Date.now();
    barcodeMasters.forEach(function (barcodeMaster) {
        barcodeMaster.BarcodeMaster = packageBarcodeID;
        barcodeMaster.AssemblyBarcode = barcodeMaster._id;
        barcodeMaster.AssemblyType = 1;
        barcodeMaster.CollectDateTime = dateNow;
        barcodeMaster.RowStatus = PublicEnum.RowStatus.Insert;
        barcodeMaster.CreatedBy = barcodeMaster.QCUser;
    });

    addPackageAssembly(barcodeMasters).then(function (result) {
        completeFun(null, result);
    }, function (err) {
        var newErr = new Error();
        newErr.leval = 9;
        newErr.title = '创建条码装配关系失败';
        newErr.message = '创建条码装配关系失败';
        completeFun(newErr);

    });

};

function addPackageAssembly(assemblyRelations) {
    var deferred = Q.defer();
    Transaction.BatchSaveByTran([
            {EntityName: 'AssemblyRelation', Records: assemblyRelations}
        ],
        function (err, result) {
            if (err) {
                deferred.reject(err);
                return;
            }
            deferred.resolve(result);
        }
    );
    return deferred.promise;
}

//更新每个芯片条码主档
exports.updateBarcodes = function (barcodeMasters, completeFun) {
    // console.log(barcodeMasters);
    barcodeMasters.forEach(function (barcodeMaster) {
        barcodeMaster.Status = 4;
        barcodeMaster.RowStatus = PublicEnum.RowStatus.Modify;
        barcodeMaster.ModifyBy = barcodeMaster._id;

    });

    updateBarcodeMasters(barcodeMasters).then(function (result) {

        completeFun(null, result);
    }, function (err) {
        // console.log("updateBarcodeMasters-----err-----"+err);
        var newErr = new Error();
        newErr.leval = 9;
        newErr.title = '更新条码主档失败';
        newErr.message = '';
        completeFun(newErr);

    });
};

function updateBarcodeMasters(barcodeMasters) {
    var deferred = Q.defer();
    Transaction.BatchSaveByTran([
            {EntityName: 'BarcodeMaster', Records: barcodeMasters}
        ],
        function (err, result) {
            if (err) {
                deferred.reject(err);
                return;
            }
            deferred.resolve(result);
        }
    );
    return deferred.promise;
}

//通过设备id，获取工位，作业信息,设备信息
//1，通过终端id到工位终端表中查找工位
//2，通过工位id到作业工位表中查找作业

exports.findLocationAndWork = function (deviceid, completeFun) {
    var locationName = ''; //工位name
    var locationId = ''; //工位Id
    var workName = ''; //作业name
    var workId = ''; //作业Id
    var deviceId = ''; //设备id
    var deviceName = ''; //设备name
    var record = {};

    findTerminal_ID(deviceid).then(function (result1) {
        deviceId = result1._id;
        deviceName = result1.Name;
        findStationTerminal(deviceId).then(function (result2) {
            locationName = result2.WorkLocation.Name;
            locationId = result2.WorkLocation._id;
            findStationWork(locationId).then(function (result3) {
                workName = result3.Work.Name;
                workId = result3.Work._id;
                record = {
                    locationName: locationName,
                    locationId: locationId,
                    workName: workName,
                    workId: workId,
                    deviceId: deviceId,
                    deviceName: deviceName
                };
                completeFun(null, record);

            }, function (err) {
                completeFun(err, record);
                alert("未找到该作业");
            });
        }, function (err) {
            alert("未找到该工位");
        });
    }, function (err) {
        alert("未找到该设备id");
    });
};


//增加条码装配关系记录
//1,查找包装货号的条码主档id

//3,增加条码装配关系AssemblyRelation
exports.insertPackageAssemblyRelation = function (packageBarcode, barcodeMasters, completeFun) {
    var packageBarcodeId = '';

    findPackageBarcodeID(packageBarcode).then(function (result1) {
        packageBarcodeId = result1._id;
        var entity = entityCollection.getEntity("AssemblyRelation");
        var addDatas = [];
        var dateNow = Date.now();
        for (var i = 0; i < barcodeMasters.length; i++) {
            addDatas.push({
                BarcodeMaster: packageBarcodeId,
                AssemblyBarcode: barcodeMasters[i]._id,
                AssemblyType: 1,
                CollectDateTime: dateNow
            });
        }
        ;

        entity.saves(addDatas, function (err, record) {
            completeFun(err, record);
        });

    }, function (err) {
        alert("未找到该包装货号");
    });
};

//增加入库记录数据
exports.insertStockingRecord = function (barcodeMasters, userId, operationId, BizRecordIds, completeFun) {
    var entity = entityCollection.getEntity("RcvRecord");
    var addDatas = [];
    var dateNow = Date.now();
    for (var i = 0; i < barcodeMasters.length; i++) {
        addDatas.push({
            BarcodeMaster: barcodeMasters[i]._id,
            Barcode: barcodeMasters[i].Barcode,
            RcvBusinessType: 0,
            BusinessDocID: barcodeIds[i].MO,
            ItemMaster: barcodeIds[i].ItemMaster,
            RcvUser: userId,
            RcvDateTime: dateNow,
            RcvQty: 1,
            RcvOperation: operationId,
            BizRecord: BizRecordIds[i]
        });
    }
    ;

    entity.saves(addDatas, function (err, record) {
        completeFun(err, record);
    });

};


//新增入库的物料集合的条码流水
exports.insertBarcodesFlow = function (barcodeMasters, deviceId, deviceName, workId, workName, locationId, locationName, userId, completeFun) {

    var operationName = ''; //工序
    var operationId = ''; //工序id

    var addDatas = [];

    // findItemMasterID(barcodeMasters[0].).then(function(result) {

    operationController.findByItemMasterAndWork2(barcodeMasters[0].ItemMaster, workId, function (err, record) {
        if (err) {
            alert("未找到对应工序");
        } else {
            if (record != null) {
                operationName = record.Name;
                operationId = record._id;

                var dateNow = Date.now();
                for (var i = 0; i < barcodeMasters.length; i++) {
                    addDatas.push({
                        BarcodeMaster: barcodeMasters[i]._id,
                        Terminal: deviceId,
                        TerminalName: deviceName,
                        Operation: operationId,
                        OperationName: operationName,
                        Work: workId,
                        WorkName: workName,
                        WorkLocation: locationId,
                        WorkLocationName: locationName,
                        Users: [userId],
                        CollectDateTime: dateNow,
                        BusinessStatus: 1,

                    });
                }
                ;
                entity.saves(addDatas, function (err, record) {
                    completeFun(err, record, operationId);
                });
            }
        }
    });
    // }, function(err) {
    //     alert("未找到对应物料");
    // });

};
//查找终端id
function findTerminal_ID(deviceid) {
    var deferred = Q.defer();
    var entityTerminal = entityCollection.getEntity("Terminal");
    entityTerminal.findOne({
            UniqueID: deviceid
        }, [{
            path: '_id'
        }, {
            path: 'Name'
        }],
        function (err, record) {
            if (err) {
                deferred.reject(err);
                return;
            } else {
                deferred.resolve(record)
            }
        }
    );
    return deferred.promise;
}
//查找工位
function findStationTerminal(terminalid) {
    var deferred = Q.defer();
    var entityStationTerminal = entityCollection.getEntity("StationTerminal");
    entityStationTerminal.findOne({
            Terminal: terminalid
        }, [{
            path: 'WorkLocation',
            select: '_id Name'
        },],
        function (err, record) {
            if (err) {
                deferred.reject(err);
                return;
            } else {
                deferred.resolve(record)
            }
        }
    );
    return deferred.promise;
}

//查找作业
function findStationWork(locationid) {
    var deferred = Q.defer();
    var entityStationWork = entityCollection.getEntity("StationWork");
    entityStationWork.findOne({
            WorkLocation: locationid
        }, [{
            path: 'Work',
            select: '_id Name'
        },],
        function (err, record) {
            if (err) {
                deferred.reject(err);
                return;
            } else {
                deferred.resolve(record)
            }
        }
    );
    return deferred.promise;
}
//查找条码对应的物料id
function findItemMasterID(barcode) {
    var deferred = Q.defer();
    var entity = entityCollection.getEntity("BarcodeMaster");
    entity.findOne({
            Barcode: barcode
        }, [{
            path: 'ItemMaster',
        }, {
            path: '_id',
        }],
        function (err, record) {
            if (err) {
                deferred.reject(err);
                return;
            } else {
                deferred.resolve(record)
            }
        }
    );
    return deferred.promise;
}
//查找包装货号的id
function findPackageBarcodeID(packageBarcode) {
    var deferred = Q.defer();
    var entity = entityCollection.getEntity("BarcodeMaster");
    entity.findOne({
            Barcode: packageBarcode
        }, [{
            path: '_id',
        }],
        function (err, record) {
            if (err) {
                deferred.reject(err);
                return;
            } else {
                deferred.resolve(record)
            }
        }
    );
    return deferred.promise;
}
//查找每个芯片的id
function findBarcodeID(Barcode) {
    var deferred = Q.defer();
    var entity = entityCollection.getEntity("BarcodeMaster");
    entity.findOne({
            Barcode: Barcode
        }, [{
            path: '_id',
        }],
        function (err, record) {
            if (err) {
                deferred.reject(err);
                return;
            } else {
                deferred.resolve(record)
            }
        }
    );
    return deferred.promise;
}

// //根据（镭射标条码）装配条码查找其条码主档id
exports.findAssemblyBarcodeMasterId = function (barcode, completeFun) {
    var entity = entityCollection.getEntity("BarcodeMaster");
    entity.findOne({
            Barcode: barcode
        }, [{
            path: '_id'
        },],
        function (err, record) {
            if (err) {
                var newErr = new Error();
                newErr.leval = 9;
                newErr.title = '查询条码主档错误';
                newErr.message = '查询失败，请检查查询参数！';
                completeFun(newErr);
            } else {
                completeFun(null, record);
            }
        }
    );
};
//根据装配的条码主档id到装配表中找到对应的主档
exports.findAssemblyBarcodeMaster = function (ID, completeFun) {
    var entity = entityCollection.getEntity("AssemblyRelation");
    entity.findOne({
            AssemblyBarcode: ID
        }, [{
            path: 'BarcodeMaster'
        },],
        function (err, record) {
            if (err) {
                var newErr = new Error();
                newErr.leval = 9;
                newErr.title = '查询条码主档错误';
                newErr.message = '查询失败，请检查查询参数！';
                completeFun(newErr);
            } else {
                completeFun(null, record);
            }
        }
    );
};
//根据条码查找条码主档
exports.findBarcodeMaster = function (barcode, completeFun) {
    var entity = entityCollection.getEntity("BarcodeMaster");
    entity.findOne({Barcode: barcode}, [
            {path: 'ItemMaster', select: 'Code Name Specification ItemCategory'},
            {path: 'MO', select: 'Code LotNumber Customer StartDateTime EndDateTime Remark'},
            {path: 'Work', select: 'Name'},
            {path: 'BizRecord'},
            {path: 'Operation'},
            {path: 'QCReworkOperation'},
            {path: 'Users', select: 'Code Name'}
        ],
        function (err, record) {
            if (err) {
                var newErr = new Error();
                newErr.leval = 9;
                newErr.title = '查询条码主档错误';
                newErr.message = '查询失败，请检查查询参数！';
                completeFun(newErr);
            } else {
                completeFun(null, record);
            }
        }
    );
};

/***
 * 根据条码查找主档信息
 * @param {String} barcode
 * @param {Function} completeFun
 */
exports.findBarcodeMasterByBarcode = function (barcode, completeFun) {
    var entity = entityCollection.getEntity("BarcodeMaster");
    entity.findOne({Barcode: barcode}, null,
        function (err, record) {
            if (err) {
                var newErr = new Error();
                newErr.leval = 9;
                newErr.title = '查询条码主档错误';
                newErr.message = '查询失败，请检查查询参数！';
                completeFun(newErr);
            } else {
                completeFun(null, record);
            }
        });
};

//根据条码主档查找条码主档所有信息
exports.findBarcodeMasterByBarcodeMaster = function (barcodeMaster, completeFun) {
    var entity = entityCollection.getEntity("BarcodeMaster");
    entity.findOne({_id: barcodeMaster}, null,
        function (err, record) {
            if (err) {
                var newErr = new Error();
                newErr.leval = 9;
                newErr.title = '查询条码主档错误';
                newErr.message = '查询失败，请检查查询参数！';
                completeFun(newErr);
            } else {
                completeFun(null, record);
            }
        });
};

//根据条码查找条码主档
exports.findBarcodeMasters = function (barcodes, populate) {
    var deferred = Q.defer();

    var entity = entityCollection.getEntity("BarcodeMaster");
    populate = populate ? populate : [
        {path: 'ItemMaster', select: 'Code Name Specification ItemCategory'},
        {path: 'MO', select: 'Code LotNumber Customer StartDateTime EndDateTime Remark'},
        {path: 'Work', select: 'Code Name'},
        {path: 'BizRecord'},
        {path: 'Operation'},
        {path: 'QCReworkOperation'},
        {path: 'Users', select: 'Code Name'}
    ];
    entity.find({
        Barcode: {$in: barcodes}
    }, {
        Barcode: 1
    }, populate, function (err, records) {
        if (err) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '查询条码主档错误';
            newErr.message = '查询失败，请检查查询参数！';
            deferred.reject(newErr);
        } else {
            deferred.resolve(records);
        }
    });

    return deferred.promise;
};

// 根据记录ID查找条码主档
exports.findBarcodeMasterById = function (barcodeMasterId) {
    var deferred = Q.defer();

    var entity = entityCollection.getEntity("BarcodeMaster");
    entity.findById(barcodeMasterId, [
            {path: 'ItemMaster', select: 'Code Name Specification ItemCategory'},
            {path: 'MO', select: 'Code LotNumber Customer StartDateTime EndDateTime Remark'},
            {path: 'Work', select: 'Name'},
            {path: 'BizRecord'},
            {path: 'Operation'},
            {path: 'QCReworkOperation'},
            {path: 'Users', select: 'Code Name'}
        ],
        function (err, record) {
            if (err) {
                var newErr = new Error();
                newErr.leval = 9;
                newErr.title = '查询条码主档错误';
                newErr.message = '查询失败，请检查查询参数！';
                deferred.reject(newErr);
                return;
            } else {
                deferred.resolve(record);
            }
        }
    );

    return deferred.promise;
};

//查找不合格条码主档
exports.findMastersByQCStatus = function (qcStatus, completeFun) {
    var entity = entityCollection.getEntity("BarcodeMaster");
    entity.Entity
        .find({
            BarcodeType: BarcodeEnum.BarcodeType.ItemMaster,
            QCStatus: qcStatus
        }, {
            Barcode: 1,
            WorkName: 1,
            WorkLocationName: 1,
            Users: 1,
            MOLotNumber: 1,
            ItemMasterCode: 1,
            ItemMasterName: 1
        })
        .populate({path: 'Users', select: 'Code Name'})
        .exec(function (err, records) {
            if (err) {
                var newErr = new Error();
                newErr.leval = 9;
                newErr.title = '查询条码主档错误';
                newErr.message = '查询失败，请检查查询参数！';
                completeFun(newErr);
            } else {
                completeFun(null, records);
            }
        });
};

exports.findUser = function (barcode, completeFun) {
    var entity = entityCollection.getEntity("BarcodeMaster");
    entity.findOne({Barcode: barcode}, null, function (err, record) {
        if (err) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '查询条码主档错误';
            newErr.message = '查询失败，请检查查询参数！';
            completeFun(newErr);
        } else {
            if (record == null) {
                var newErr = new Error();
                newErr.leval = 9;
                newErr.title = '查询条码主档失败';
                newErr.message = '该条码在系统中不存在！';
                completeFun(newErr);
            } else {
                if (record.BarcodeType != BarcodeEnum.BarcodeType.Person) {
                    var newErr = new Error();
                    newErr.leval = 9;
                    newErr.title = '查询员工信息失败';
                    newErr.message = '该条码不是员工条码！';
                    completeFun(newErr);
                } else {
                    userController.getUserAndRolesInfo(record.EntityID, function (err, user) {
                        completeFun(err, user);
                    });
                }
            }
        }
    });
};

exports.updateByValue = function (barcode, value, completeFun) {
    var entity = entityCollection.getEntity("BarcodeMaster");
    entity.updateByValue({Barcode: barcode}, value, function (err, result) {
        completeFun(err, result);
    });
};
/**
 * [findBarcodeMasterByCoditions 根据条件查询条码主档]
 * author jiadx
 * @param  MOLotNumber     [批次（可为空）]
 * @param  completeFun
 * @return {[type]}             [条码主档记录]
 */
exports.findAllBarcodeMaster = function (optNum, completeFun) {
    var entityDepartment = entityCollection.getEntity("WorkLocation");
    //查询工位和部门保存到对象，作为对照表

    entityDepartment.find({}, null, {
        path: 'Department',
        select: 'Code Name'
    }, function (err, records) {
        if (err) {
            completeFun(err);
            return;
        }
        var department = {};
        records.forEach(function (record) {
            if (!department.hasOwnProperty(record._id)) {
                department[record._id] = {
                    workLocation: record._id,
                    departmentCode: record.Department ? record.Department.Code : '',
                    department: record.Department ? record.Department.Name : ''
                };
            }
        });
        //条码主档进行分组
        var entity = entityCollection.getEntity("BarcodeMaster");
        var barcodeMap = function () {
            emit(this.MOLotNumber, {WorkLocations: [this.WorkLocation]});
        };
        var barcodeReduce = function (key, values) {
            var res = {WorkLocations: []};
            values.forEach(function (val) {
                val.WorkLocations.forEach(function (WorkLocation) {
                    res.WorkLocations.push(WorkLocation);
                });
            });
            return res;
        };

        var barcodeQuery = {
            IsComplete: false,
            Status: {$nin: [5]}
        };

        if (optNum) {
            barcodeQuery.MOLotNumber = {$in: optNum};
        }

        var option = {
            map: barcodeMap,
            reduce: barcodeReduce,
            sort: {MOLotNumber: -1},
            query: barcodeQuery
        };

        entity.mapReduce(option, function (err, results) {
            if (err) {
                completeFun(err);
                return;
            }
            var resultObj = {};
            for (var i = 0; i < results.length; i++) {
                var lastResult = {};
                for (var j = 0; j < results[i].value.WorkLocations.length; j++) {
                    if (department.hasOwnProperty(results[i].value.WorkLocations[j])) {
                        results[i].value.WorkLocations[j] = department[results[i].value.WorkLocations[j]].department;
                        if (!lastResult.hasOwnProperty(results[i].value.WorkLocations[j])) {
                            lastResult[results[i].value.WorkLocations[j]] = 0;
                        }
                        if (lastResult.hasOwnProperty(results[i].value.WorkLocations[j])) {
                            lastResult[results[i].value.WorkLocations[j]] += 1;
                        }
                    }
                }
                resultObj[results[i]._id] = lastResult;
            }
            completeFun(err, resultObj);
        });
    });
};

//插入条码主档
exports.createBarcodeMaster = function (barcodeMasterData, completeFun) {
    var barcodeMasterEntity = entityCollection.getEntity("BarcodeMaster");
    barcodeMasterEntity.insert(barcodeMasterData, function (err, newBarcodeMaster) {
        completeFun(err, newBarcodeMaster);
    });
};

//删除条码主档
exports.deleteById = function (id, completeFun) {
    var barcodeMasterEntity = entityCollection.getEntity("BarcodeMaster");
    barcodeMasterEntity.deleteById(id, function (err, result) {
        completeFun(err, result);
    });
};

//端应用流水校验
//barcodeMaster包含字段：QCStatus、QCReworkOperation、Operation
//bindContext包含字段：Work、WorkName、WorkLacation、WorkLacationName、User
exports.streamValidation = function (barcodeMasters, bindOperation, bindContext, containModify) {
    var deferred = Q.defer();

    if (!_.isArray(barcodeMasters)) {
        barcodeMasters = [barcodeMasters];
    }
    checkStream(barcodeMasters[0], bindOperation, containModify).then(function (result) {
        if (!result) {
            deferred.resolve();
        } else {
            if (result.exceptionType === BarcodeEnum.ExceptionType.DrainScard) {
                if (bindContext) {
                    var batches = [];
                    _.forEach(barcodeMasters, function (barcodeMaster) {
                        batches.push(processExceptionController.writeProcessException(
                            barcodeMaster, bindContext, result.exceptionType, result.missingOperations
                        ));
                    });
                    Q.all(batches).finally(function () {
                        deferred.resolve();
                    });
                } else {
                    deferred.resolve();
                } 
            } else {
                deferred.reject(result.error);
            }
        }
    }, function (err) {
        deferred.reject(err);
    });

    return deferred.promise;
};

//读头流水校验
//barcodeMaster包含字段：QCStatus、QCReworkOperation、Operation
//bindContext包含字段：Work、WorkName、WorkLacation、WorkLacationName、User
exports.streamValidationReader = function (barcodeMaster, bindOperation, bindContext, containModify) {
    var deferred = Q.defer();

    checkStream(barcodeMaster, bindOperation, containModify).then(function (result) {
        if (!result) {
            deferred.resolve();
        } else {
            processExceptionController.writeProcessException(
                barcodeMaster, bindContext, result.exceptionType, result.missingOperations
            ).finally(function () {
                if (result.exceptionType === BarcodeEnum.ExceptionType.DrainScard) {
                    deferred.resolve();
                } else {
                    deferred.reject(result.error);
                }
            });
        }
    }, function (err) {
        deferred.reject(err);
    });

    return deferred.promise;
};

function checkStream (barcodeMaster, bindOperation, containModify) {
    var deferred = Q.defer();

    var newErr;
    if (barcodeMaster.QCStatus === QCEnum.QCStatus.Scrap) {
        newErr = new Error();
        newErr.leval = 9;
        newErr.title = '报废扫描';
        newErr.message = '该单品已报废';
        deferred.resolve({
            exceptionType: BarcodeEnum.ExceptionType.ScrappedScan,
            error: newErr
        });
    } else if (barcodeMaster.QCReworkOperation) {
        if (bindOperation.Sequence > barcodeMaster.QCReworkOperation.Sequence) {
            newErr = new Error();
            newErr.leval = 9;
            newErr.title = '返工异常扫描';
            newErr.message = '返工异常扫描，请到返工工序进行扫描';
            deferred.resolve({
                exceptionType: BarcodeEnum.ExceptionType.ReworkScan,
                error: newErr
            });
        } else {
            deferred.resolve();
        }
    } else if (bindOperation && 
        barcodeMaster.Operation && 
        bindOperation._id.toString() === barcodeMaster.Operation._id.toString() &&
        bindOperation.IsMultScan
    ) {
        deferred.resolve();
    } else {
        if ((containModify || bindOperation.IsTiming) &&
            barcodeMaster.Work && bindOperation.Work &&
            (barcodeMaster.Work._id.toString() === bindOperation.Work._id.toString())
        ) {
            deferred.resolve();
        } else {
            var routing = barcodeMaster.Operation ? barcodeMaster.Operation.Routing : bindOperation.Routing,
                sequence = barcodeMaster.Operation ? barcodeMaster.Operation.Sequence : -1;
            operationController.findNextSequence(routing, sequence).then(function (nextSequence) {
                var newErr;
                if (!nextSequence) {
                    newErr = new Error();
                    newErr.leval = 9;
                    newErr.title = '异常扫描';
                    newErr.message = '没有找到该单品的下一工序';
                    deferred.reject(newErr);
                } else if (bindOperation.Sequence > nextSequence) {
                    operationController.findMissingOperation(
                        routing, bindOperation.Sequence, sequence, {Work: 1}, {path: 'Work', select: 'Name'}
                    ).then(function (missingOperations) {
                        if (missingOperations && missingOperations.length > 0) {
                            deferred.resolve({
                                exceptionType: BarcodeEnum.ExceptionType.DrainScard,
                                missingOperations: missingOperations
                            });
                        } else {
                            deferred.resolve();
                        }
                    }, function (err) {
                        deferred.reject(err);
                    });
                } else if (bindOperation.Sequence < nextSequence) {
                    newErr = new Error();
                    newErr.leval = 9;
                    newErr.title = '逆序扫描';
                    newErr.message = '逆序扫描。当前工序：' + barcodeMaster.Operation.Name + '，' + '扫描工序：' + bindOperation.Name;
                    deferred.resolve({
                        exceptionType: BarcodeEnum.ExceptionType.ReverseScan,
                        error: newErr
                    });
                } else {
                    deferred.resolve();
                }
            }, function (err) {
                deferred.reject(err);
            });
        }
    }

    return deferred.promise;
}

/**
 * 根据物料,尺寸,外观分组
 * @param barcodes
 * @param completeFun
 * @author jiadx
 */
exports.groupFromBarcodeMaster = function (barcodes, completeFun) {
    var entity = entityCollection.getEntity("BarcodeMaster");

    var barcodeQuery = {
        Barcode: {$in: barcodes}
    };

    var barcodeMap = function () {
        emit({'ItemMaster': this.ItemMaster, 'DescSeg1': this.DescSeg1, 'DescSeg2': this.DescSeg2}, {count: 1});
    };

    var barcodeReduce = function (key, values) {
        var total = 0;
        for (var i in values) {
            total += values[i].count
        }
        return {count: total};
    };

    var option = {
        query: barcodeQuery,
        map: barcodeMap,
        reduce: barcodeReduce
    };

    entity.mapReduce(option, function (err, result) {
        if (err) {
            completeFun(err);
        } else {
            completeFun(err, result);
        }
    });
};
